// -----------------------------------------------------------------------
//  <copyright file="IQueryRepositoryBase.cs" company="LiuliuSoft">
//      Copyright (c) 2022-2022 DaprPlus. All rights reserved.
//  </copyright>
//  <site>https://www.dapr.plus</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2022-10-30 23:12</last-date>
// -----------------------------------------------------------------------

using OSharp.Filter;


namespace DaprPlus.Domain.Entity;

/// <summary>
/// 定义通用只读仓储功能
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public interface IQueryRepository<TEntity> where TEntity : class, IEntity
{
    /// <summary>
    /// 获取数据上下文
    /// </summary>
    IDbContext DbContext { get; }

    /// <summary>
    /// 获取指定实体主键编号的实体
    /// </summary>
    /// <typeparam name="TKey">实体类型</typeparam>
    /// <param name="id">实体编号</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<TEntity?> FindAsync<TKey>(TKey id, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取所有实体总数量
    /// </summary>
    Task<int> GetCountAsync(CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取所有符合规约的实体数量
    /// </summary>
    /// <param name="specification">规约</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<int> GetCountAsync(ISpecification<TEntity> specification, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取所有实体总数量
    /// </summary>
    Task<long> GetLongCountAsync(CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取所有符合规约的实体数量
    /// </summary>
    /// <param name="specification">规约</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<long> GetLongCountAsync(ISpecification<TEntity> specification, CancellationToken cancellationToken = default);

    /// <summary>
    /// 是否存在指定编号的实体
    /// </summary>
    /// <param name="id">实体编号</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<bool> AnyAsync(long id, CancellationToken cancellationToken = default);

    /// <summary>
    /// 是否存在指定规约的实体
    /// </summary>
    /// <param name="specification">规约</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<bool> AnyAsync(ISpecification<TEntity> specification, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取符合指定规约的第一个实体或Null
    /// </summary>
    /// <param name="specification">规约</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<TEntity?> GetAsync(ISpecification<TEntity> specification, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取符合指定规约的第一个实体投影或默认值
    /// </summary>
    /// <typeparam name="TResult">投影类型</typeparam>
    /// <param name="specification">规约</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<TResult?> GetAsync<TResult>(ISpecification<TEntity> specification,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取符合指定规约的第一个实体投影或默认值
    /// </summary>
    /// <typeparam name="TResult">投影类型</typeparam>
    /// <param name="specification">规约</param>
    /// <param name="selector">投影筛选器</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<TResult?> GetAsync<TResult>(ISpecification<TEntity> specification, Expression<Func<TEntity, TResult>> selector,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取所有符合规约的实体集合
    /// </summary>
    /// <param name="specification">规约</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<List<TEntity>> GetAllAsync(ISpecification<TEntity> specification, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取所有符合规约的实体投影集合
    /// </summary>
    /// <typeparam name="TResult">投影类型</typeparam>
    /// <param name="specification">规约</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<List<TResult>> GetAllAsync<TResult>(ISpecification<TEntity> specification, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取所有符合规约的实体投影集合
    /// </summary>
    /// <typeparam name="TResult">投影类型</typeparam>
    /// <param name="specification">规约</param>
    /// <param name="selector">投影筛选器</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<List<TResult>> GetAllAsync<TResult>(ISpecification<TEntity> specification, Expression<Func<TEntity, TResult>> selector, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取所有符合规约的分页实体集合
    /// </summary>
    /// <param name="specification">规约</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<PageResult<TEntity>> GetPageAsync(ISpecification<TEntity> specification, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取所有符合规约的分页实体投影集合
    /// </summary>
    /// <typeparam name="TResult">投影类型</typeparam>
    /// <param name="specification">规约</param>
    /// <param name="selector">投影筛选器</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<PageResult<TResult>> GetPageAsync<TResult>(ISpecification<TEntity> specification, Expression<Func<TEntity, TResult>> selector, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取所有符合规约的分页实体投影集合
    /// </summary>
    /// <typeparam name="TResult">投影类型</typeparam>
    /// <param name="specification">规约</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<PageResult<TResult>> GetPageAsync<TResult>(ISpecification<TEntity> specification,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 查询指定SQL查询
    /// </summary>
    /// <typeparam name="TResult">结果类型</typeparam>
    /// <param name="sql">查询的SQL语句</param>
    /// <param name="param">SQL参数</param>
    /// <returns></returns>
    Task<List<TResult>> FromSql<TResult>(string sql, object? param = null);

    /// <summary>
    /// 查询指定SQL查询
    /// </summary>
    /// <param name="sql">查询的SQL语句</param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<List<TEntity>> FromSql(FormattableString sql, CancellationToken cancellationToken = default);
}
